package com.qiantu.phone.widget;

import static java.lang.annotation.RetentionPolicy.SOURCE;

import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.qiantu.phone.R;
import com.qiantu.phone.app.AppActivity;
import com.qiantu.phone.glide.GlideApp;
import com.rd.utils.DensityUtils;
import java.lang.annotation.Retention;

/**
 * 从底部往上弹出View
 */
public abstract class BasePopupView extends FrameLayout {
    private View bgView;
    private LinearLayout frView;
    private FrameLayout indicatorLayout;
    private View indicatorView;
    private boolean touchIndicator;//是否拖住的小灰条
    private GestureDetector gestureDetector;//触摸小灰条往下拽实现隐藏popupView

    public BasePopupView(@NonNull Context context) {
        super(context);
        init(context);
    }

    public BasePopupView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    private void init(Context context) {
        initGestureDetector(context);
        initBgView(context);

        initFrView(context);

        initIndicator(context);

        initContentView(context);

        initView(context);
    }

    /**
     * 初始化具体实现的View
     *
     * @param context 上下文
     */
    private void initContentView(Context context) {
        View contentView = loadLayout(context);
        contentView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        frView.addView(contentView);

        View bottomView = new View(context);
        bottomView.setLayoutParams(new LinearLayout.LayoutParams(0, DensityUtils.dpToPx(16)));
        frView.addView(bottomView);
    }

    /**
     * 初始化小灰条
     *
     * @param context 上下文
     */
    private void initIndicator(Context context) {
        indicatorLayout = new FrameLayout(context);
        indicatorLayout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));

        indicatorView = new View(context);
        LayoutParams inLp = new LayoutParams(DensityUtils.dpToPx(40), DensityUtils.dpToPx(4));
        inLp.topMargin = DensityUtils.dpToPx(16);
        inLp.bottomMargin = DensityUtils.dpToPx(16);
        inLp.gravity = Gravity.CENTER_HORIZONTAL;
        indicatorView.setLayoutParams(inLp);
        indicatorView.setBackgroundResource(R.drawable.bg_indicator_view);
        indicatorLayout.addView(indicatorView);
        frView.addView(indicatorLayout);
    }

    /**
     * 初始化白色操作面板
     *
     * @param context
     */
    private void initFrView(Context context) {
        frView = new LinearLayout(context);
        LayoutParams lp = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        lp.gravity = Gravity.BOTTOM;
        frView.setLayoutParams(lp);
        frView.setOrientation(LinearLayout.VERTICAL);
        frView.setBackgroundResource(R.drawable.bg_base_popup_radius);
        frView.setOnClickListener(v -> {
        });
        addView(frView);
    }

    /**
     * 初始化手势检测 用来操作小灰条来滑动
     *
     * @param context 上下文
     */
    private void initGestureDetector(Context context) {
        gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
                float scrollY = frView.getTranslationY() - distanceY;
                if (scrollY < 0)
                    scrollY = 0;
                frView.setTranslationY(scrollY);
                float alpha = distanceY > 0 ? bgView.getAlpha() + 0.01f : bgView.getAlpha() - 0.01f;
                if (alpha >= 0.7f) {
                    alpha = 0.7f;
                } else if (alpha <= 0f) {
                    alpha = 0f;
                }
                bgView.setAlpha(alpha);
                frView.invalidate();
                return super.onScroll(e1, e2, distanceX, distanceY);
            }

            @Override
            public boolean onDown(MotionEvent e) {
                indicatorView.setBackgroundResource(R.drawable.bg_indicator_view_pre);
                return true;
            }
        });
    }

    /**
     * 初始化背景阴影View
     *
     * @param context 上下文
     */
    private void initBgView(Context context) {
        bgView = new View(context);
        bgView.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        bgView.setBackgroundColor(Color.BLACK);
        bgView.setClickable(true);
        bgView.setOnClickListener(view -> {

            setVisibility(GONE);
        });
        addView(bgView);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (isTouchPointInView(indicatorLayout, ev.getX(), ev.getY())) {
                    touchIndicator = true;
                    return gestureDetector.onTouchEvent(ev);
                }
                return super.dispatchTouchEvent(ev);
            case MotionEvent.ACTION_MOVE:
                if (touchIndicator) {
                    return gestureDetector.onTouchEvent(ev);
                }
                return super.dispatchTouchEvent(ev);
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                if (touchIndicator) {
                    touchIndicator = false;
                    indicatorView.setBackgroundResource(R.drawable.bg_indicator_view);
                    int warnHeight = frView.getHeight() / 2;
                    if (frView.getTranslationY() > warnHeight) {//超过高度一半就退出
                        setVisibility(GONE);
                    } else {//否则回到原先位置
                        ObjectAnimator.ofFloat(frView, "translationY", frView.getTranslationY(), 0)
                                .setDuration(200).start();
                        ObjectAnimator.ofFloat(bgView, "alpha", bgView.getAlpha(), 0.7f)
                                .setDuration(200).start();
                    }
                }
                return super.dispatchTouchEvent(ev);
        }
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public void setVisibility(int visibility) {
        if (visibility == VISIBLE) {//执行弹起动画
            super.setVisibility(visibility);
            if (frView.getTranslationY() == 0)//这里是第一次弹出会拿不到view高度导致没有动画，所以给它设置下屏幕高度
                frView.setTranslationY(com.hjq.base.DensityUtils.getScreenHeight(getContext()));
            ObjectAnimator.ofFloat(frView, "translationY", frView.getTranslationY(), 0)
                    .setDuration(200).start();
            ObjectAnimator.ofFloat(bgView, "alpha", 0f, 0.7f)
                    .setDuration(200).start();
        } else {//执行隐藏动画
            ObjectAnimator.ofFloat(frView, "translationY", frView.getTranslationY(), getHeight())
                    .setDuration(200).start();
            ObjectAnimator.ofFloat(bgView, "alpha", bgView.getAlpha(), 0f)
                    .setDuration(200).start();
            bgView.postDelayed(new Runnable() {
                @Override
                public void run() {
                    BasePopupView.super.setVisibility(visibility);//动画结束后才执行系统的隐藏view
                }
            }, 200);

        }

    }

    private boolean isTouchPointInView(View view, float x, float y) {
        if (view == null) {
            return false;
        }
        int[] position = new int[2];
        view.getLocationOnScreen(position);
        int left = position[0];
        int top = position[1];
        int right = left + view.getMeasuredWidth();
        int bottom = top + view.getMeasuredHeight();
        return x >= left && x <= right && y >= top && y <= bottom;
    }

    /**
     * imageview绑定数据
     *
     * @param imageViewId imageviewId
     * @param resId       资源id
     */
    protected void setImageViewBind(int imageViewId, int resId) {
        GlideApp.with(getContext())
                .load(resId)
                .into((ImageView) findViewById(imageViewId));
    }

    /**
     * imageview绑定数据
     *
     * @param imageViewId imageviewId
     * @param url         网络路径
     */
    protected void setImageViewBind(int imageViewId, String url) {
        GlideApp.with(getContext())
                .load(url)
                .into((ImageView) findViewById(imageViewId));
    }

    /**
     * textview绑定数据
     *
     * @param textviewId 文本控件id
     * @param resId      资源id
     */
    protected void setTextViewBind(int textviewId, int resId) {
        ((TextView) findViewById(textviewId)).setText(resId);
    }

    /**
     * textview绑定数据
     *
     * @param textviewId 文本控件id
     * @param resId      资源id
     * @param format     格式化数据 比如 %s个场景
     */
    protected void setTextViewBind(int textviewId, int resId, String... format) {
        ((TextView) findViewById(textviewId)).setText(String.format(getResources().getString(resId), (Object[]) format));
    }

    /**
     * textview绑定数据
     *
     * @param textviewId 文本控件id
     * @param text       文本
     * @param format     格式化数据 比如 %s个场景
     */
    protected void setTextViewBind(int textviewId, String text, String... format) {
        ((TextView) findViewById(textviewId)).setText(String.format(text, (Object[]) format));
    }


    @Retention(SOURCE)
    @IntDef({android.view.View.VISIBLE, android.view.View.INVISIBLE, android.view.View.GONE})
    public @interface Visibility {
    }

    /**
     * 设置View显示隐藏
     *
     * @param viewId     viewId
     * @param visibility 控制显示隐藏 View.GONE,
     */
    protected void setVisibilityBind(int viewId, @AppActivity.Visibility int visibility) {
        findViewById(viewId).setVisibility(visibility);
    }

    /**
     * 获取view显示状态
     *
     * @param viewId viewId
     * @return 返回visibility
     */
    protected int getVisibilityBind(int viewId) {
        return findViewById(viewId).getVisibility();
    }

    protected abstract View loadLayout(Context context);

    protected abstract void initView(Context context);

}
